

package Addr2Line ;

use strict ;
use warnings;
use bytes;
use integer;

use File::Temp 'tempfile' ;
use FileHandle;
use Carp;

sub new {
    my ($class, $file, $exec) = @_ ;
    $file or carp "file parameter required" ;
    -f $file or carp "$file: not exists" ;
    bless [$exec || 'addr2line', $file], $class ;
}

sub asm_lines($) {
    no warnings 'portable';
    my ($self, $asm) = @_ ;
    my ($fh, $tempfile) = tempfile();
    for (split /^/, $asm) {
        /^\W*0x0*([\da-f]+)\b/i or next;
        print $fh $1, "\n";
    }
    close $fh ;
    $fh = new FileHandle ("$self->[0] -a -i -s -e $self->[1] < $tempfile |" ) or carp "Can't execute $self->[0]: $!\n" ;
    my %ret;
    my $a ;
    my @v ;
    while (1) {
        my $l = $fh->getline() or last ;
        chomp $l ;
        if ($l =~ /^\s*0x[\da-f]+\s*$/i) {
            $ret{$a} = join ':', @v if $a and @v ;
            ($a, @v) = hex $l ;
        }
        else {
            push @v, $l;
        }
    }
    unlink $tempfile;
    \%ret ;
}

1
